package org.zn.mvcbase.config;


import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.zn.commons.collection.Maps;
import org.zn.commons.easiness.DataSources;
import org.zn.commons.loader.PackageScanner;
import org.zn.commons.serialno.Sequence;
import org.zn.mvcbase.config.property.BootMvcProperty;
import org.zn.mvcbase.exception.ApplicationJsonResponseRegister;
import org.zn.mvcbase.exception.CommonExceptionResolver;
import org.zn.mvcbase.exception.ExceptionResponseMessageFactory;
import org.zn.mvcbase.exception.ExceptionResponseRegister;
import org.zn.mvcbase.exception.ExceptionResponseStateFactory;
import org.zn.mvcbase.mybatis.ddl.AutoTableCreater;
import org.zn.mvcbase.mybatis.ddl.Ddldao;
import org.zn.mvcbase.mybatis.ddl.SqlTypeMapping;
import org.zn.mvcbase.mybatis.ddl.TableEntity;
import org.zn.mvcbase.mybatis.ddl.TableEntityProvider;
import org.zn.mvcbase.response.CommonDataConventer;
import org.zn.mvcbase.response.DataConverter;
import org.zn.mvcbase.response.EasyUIDataGridConverter;
import org.zn.mvcbase.response.JqGridConverter;
import org.zn.mvcbase.response.ResponseMessageFactory;
import org.zn.mvcbase.response.VariableDataGridConverter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;

@Configuration
//@PropertySource(value = {"classpath:bootConfig/boot-plugin.properties"},encoding="utf-8")
@ConfigurationProperties(prefix = "bootmvc")
@EnableConfigurationProperties(value =  {BootMvcProperty.class})
public class BootConfig {

	private static transient final Logger log = LoggerFactory.getLogger(BootConfig.class);


	 @Autowired
	 private BootMvcProperty bootMvcProperty;
	 
	 private String[] dialect =new  String[]{"mysql","mariadb","oracle","sqlserver"};
	
	@PostConstruct
	public void initLog() {
		
		log.info("{} init","BootConfig");
		
	}
	
	

		
	
	@Bean
	@Scope("singleton")
	public ResponseMessageFactory rmfactory() throws ClassNotFoundException {
		
		log.info("ResponseMessageFactory init");
		
		ResponseMessageFactory rmf=new ResponseMessageFactory();
		
		Map<String, DataConverter> map=Maps.newMap();
		
		CommonDataConventer cdc=new CommonDataConventer();
		
		
		VariableDataGridConverter edg=new VariableDataGridConverter(map, bootMvcProperty.getResponseMessage().getGridClass());
		
		map.put("variableGrid", edg);
	
		map.put("easyUIGrid", new EasyUIDataGridConverter());
				
		map.put("jqGrid", new JqGridConverter());
		
		map.put("datamessage", cdc);
		map.put("pagedata", cdc);
		map.put("mainstatus", cdc);
		map.put("validmessage", cdc);
		map.put("detail", cdc);
		rmf.setConvertermapper(map);
		

		
		return rmf;
		
	}
	
	
	@Bean
	@ConditionalOnProperty(prefix="bootmvc" ,name="errorAdvice",havingValue="true",matchIfMissing=false)
	public CommonExceptionResolver commonExceptionResolver() {
		
		CommonExceptionResolver  ce=new CommonExceptionResolver();
		
		ce.setDefaultExceptionPage(bootMvcProperty.getException().getDefaultpage());
		
		return ce;
	
	}
	
	@Bean
	@ConditionalOnProperty(prefix="bootmvc" ,name="errorAdvice",havingValue="true",matchIfMissing=false)
	public   ExceptionResponseStateFactory exceptionResponseStateFactory(){
		
		ExceptionResponseStateFactory ersf=new ExceptionResponseStateFactory();
		
	  List<ExceptionResponseRegister>list= Lists.newArrayList();
	  
	  list.add(new ApplicationJsonResponseRegister(3));
		
		ersf.setRegistry(list);
		
		return  ersf;
	}
	
	
	@Bean
	@ConditionalOnProperty(prefix="bootmvc" ,name="errorAdvice",havingValue="true",matchIfMissing=false)
	public ExceptionResponseMessageFactory exceptionResponseMessageFactory() {
		
		ExceptionResponseMessageFactory ermf=new ExceptionResponseMessageFactory(bootMvcProperty.getException().getErmPackage());		
		
		return ermf;
		
	}
	
	@Bean
	public ObjectMapper objectMapper() {
		
		ObjectMapper om=new ObjectMapper();
		
		return om;
		
	}
	
	@Bean
	@ConditionalOnBean(value=SqlTypeMapping.class)
	public TableEntityProvider tableEntityProvider(SqlTypeMapping  typeMapping) throws SQLException {
		
		TableEntityProvider tep= new TableEntityProvider();
			
		tep.setTypeMapping(typeMapping);
			
		return tep;
		
	}
	
	@Bean
	@ConditionalOnBean(type="javax.sql.DataSource")
	public SqlTypeMapping sqlTypeMapping(@Autowired(required=false)DataSource dataSource) throws SQLException {
		
		SqlTypeMapping stm=null;
		
		if(dataSource!=null) {
		
		String dialect=DataSources.dialect(DataSources.getUrl(dataSource));
		
		 stm=	new SqlTypeMapping(dialect);
			
		}
		
		return stm;
		
	}
	
	
	
	@ConditionalOnProperty(prefix="bootmvc.mybatis" ,name="autoTableCreate",havingValue="true",matchIfMissing=false)
	@Bean
	public AutoTableCreater autoTableCreater(DataSource dataSource,Ddldao ddl,TableEntityProvider provider,PackageScanner packageScanner) throws SQLException, IOException {
		
		//String  defualtSchema=DataSources.getSchema(dataSource);
		
		AutoTableCreater autoTableCreater=new AutoTableCreater();
		
		autoTableCreater.setDdldao(ddl);
		autoTableCreater.setDefaultSchema(null);
		autoTableCreater.setPackageScanner(packageScanner);
		autoTableCreater.setProvider(provider);
		
		autoTableCreater.setPackages(bootMvcProperty.getMybatis().getEntityPackages());
		autoTableCreater.setMode(bootMvcProperty.getMybatis().getTableCreateMode());
		
		
		autoTableCreater.createrTable();
		
		return autoTableCreater;	
	}
	
	
	@Bean
	public PackageScanner packageScanner() {
		return new PackageScanner();
	}
	
	
	@ConditionalOnProperty(prefix="bootmvc.seq" ,name="autoTable",havingValue="true",matchIfMissing=false)
	@Bean("seqTable")
	public String autoSequenceTable(Ddldao ddl,TableEntityProvider provider) {
		
	
	  TableEntity te=  provider.provide(Sequence.class);
	  
	  int flag = ddl.hasTableflag(te.getSchema() == null ? "" : te.getSchema(),
			  te.getTableName());
	
	  if(flag==0) {
	  ddl.createTable(te.getSchema(), te.getTableName(), te.getColumns(), te.getIds().get(0));
	
	 
	  }
	  return "ready";
	  
	  
	   
	}

	
}
